home *** CD-ROM | disk | FTP | other *** search
- /* --------------------------- 3DSRDR.C -------------------------------
- .3DS file format exerciser. Written by Jare/Iguana. v1.0.
- I compile this with Watcom/32, but I guess it should work with
- any compiler and OS combination for which the typedefs are
- valid i.e. any that I know for PCs... Try it and see.
- Oh, and also check the #pragma pack() thing.
-
- Heavily based on info on the file 3DS_08.TXT by Jim Pitts
- (jp5@ukc.ac.uk)
-
- Basic material-related stuff digged up by Jare.
-
- If you decide to work on this further, please make your findings
- public like we have already done, ok? Upload it to
- x2ftp.oulu.fi, THE place for programming info.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- typedef unsigned char byte;
- typedef unsigned short word;
- typedef unsigned long dword;
-
- #pragma pack(2)
-
- typedef struct {
- word id;
- dword len;
- } TChunkHeader, *PChunkHeader;
-
- #pragma pack()
-
- enum {
- CHUNK_RGBF = 0x0010,
- CHUNK_RGBB = 0x0011,
- // CHUNK_RBGB2 = 0x0012, // ?? NOT HLS.
-
- CHUNK_MAIN = 0x4D4D,
- CHUNK_OBJMESH = 0x3D3D,
- CHUNK_BKGCOLOR = 0x1200,
- CHUNK_AMBCOLOR = 0x2100,
- CHUNK_OBJBLOCK = 0x4000,
- CHUNK_TRIMESH = 0x4100,
- CHUNK_VERTLIST = 0x4110,
- CHUNK_FACELIST = 0x4120,
- CHUNK_FACEMAT = 0x4130,
- CHUNK_MAPLIST = 0x4140,
- CHUNK_SMOOLIST = 0x4150,
- CHUNK_TRMATRIX = 0x4160,
- CHUNK_LIGHT = 0x4600,
- CHUNK_SPOTLIGHT = 0x4610,
- CHUNK_CAMERA = 0x4700,
- CHUNK_MATERIAL = 0xAFFF,
- CHUNK_MATNAME = 0xA000,
- CHUNK_AMBIENT = 0xA010,
- CHUNK_DIFFUSE = 0xA020,
- CHUNK_SPECULAR = 0xA030,
- CHUNK_TEXTURE = 0xA200,
- CHUNK_BUMPMAP = 0xA230,
- CHUNK_MAPFILE = 0xA300,
- CHUNK_KEYFRAMER = 0xB000,
- CHUNK_FRAMES = 0xB008,
-
- };
-
- // ------------------------------------
-
- // Forward declaration.
- void ChunkReader(FILE *f, int ind, long p);
-
- void SkipReader(FILE *f, int ind, long p) {
- }
-
- void RGBFReader (FILE *f, int ind, long p) {
- float c[3];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s Red: %f, Green: %f, Blue: %f\n", ind, "", c[0], c[1], c[2]);
- }
-
- void RGBBReader (FILE *f, int ind, long p) {
- byte c[3];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s Red: %d, Green: %d, Blue: %d\n", ind, "", c[0], c[1], c[2]);
- }
-
- void ObjBlockReader (FILE *f, int ind, long p) {
- int c;
-
- // Read ASCIIZ object name
- printf("%*sObject name \"", ind, "");
- while ( (c = fgetc(f)) != EOF && c != '\0')
- putchar(c);
- printf("\"\n");
- // Read rest of chunks inside this one.
- ChunkReader(f, ind, p);
- }
-
- void VertListReader (FILE *f, int ind, long p) {
- word nv;
- float c[3];
-
- if (fread(&nv, sizeof(nv), 1, f) != 1) return;
- printf("%*sVertices: %d\n", ind, "", nv);
- while (nv-- > 0) {
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s X: %f, Y: %f, Z: %f\n", ind, "", c[0], c[1], c[2]);
- }
- }
-
- void FaceListReader (FILE *f, int ind, long p) {
- word nv;
- word c[4];
-
- if (fread(&nv, sizeof(nv), 1, f) != 1) return;
- printf("%*sFaces: %d\n", ind, "", nv);
- while (nv-- > 0) {
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s A: %d, B: %d, C: %d, Flags 0x%X\n",
- ind, "", c[0], c[1], c[2], c[3]);
- }
- // Read rest of chunks inside this one.
- ChunkReader(f, ind, p);
- }
-
- void FaceMatReader (FILE *f, int ind, long p) {
- int c;
- word n, nf;
-
- // Read ASCIIZ material name
- printf("%*sMaterial name for faces: \"", ind, "");
- while ( (c = fgetc(f)) != EOF && c != '\0')
- putchar(c);
- printf("\"\n");
-
- if (fread(&n, sizeof(n), 1, f) != 1) return;
- printf("%*sFaces with this material: %d\n", ind, "", n);
- while (n-- > 0) {
- if (fread(&nf, sizeof(nf), 1, f) != 1) return;
- printf("%*s Face %d\n",
- ind, "", nf);
- }
- }
-
- void MapListReader (FILE *f, int ind, long p) {
- word nv;
- float c[2];
-
- if (fread(&nv, sizeof(nv), 1, f) != 1) return;
- printf("%*sVertices: %d\n", ind, "", nv);
- while (nv-- > 0) {
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s U: %f, V: %f\n", ind, "", c[0], c[1]);
- }
- }
-
- void SmooListReader (FILE *f, int ind, long p) {
- dword s;
- int i;
-
- while (ftell(f) < p) {
- if (fread(&s, sizeof(s), 1, f) != 1) return;
- printf("%*sSmoothing groups: ", ind, "");
- for (i = 0; i < 32; i++)
- if (s & (1 << i))
- printf("%d, ", i + 1);
- printf("\n");
- }
- }
-
- void TrMatrixReader(FILE *f, int ind, long p) {
- float rot[9];
- float trans[3];
- if (fread(&rot, sizeof(rot), 1, f) != 1) return;
- printf("%*sRotation matrix:\n", ind, "");
- printf("%*s %f, %f, %f\n", ind, "", rot[0], rot[1], rot[2]);
- printf("%*s %f, %f, %f\n", ind, "", rot[3], rot[4], rot[5]);
- printf("%*s %f, %f, %f\n", ind, "", rot[6], rot[7], rot[8]);
- if (fread(&trans, sizeof(trans), 1, f) != 1) return;
- printf("%*sTranslation matrix: %f, %f, %f\n",
- ind, "", trans[0], trans[1], trans[2]);
- }
-
- void LightReader(FILE *f, int ind, long p) {
- float c[3];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s X: %f, Y: %f, Z: %f\n", ind, "", c[0], c[1], c[2]);
- // Read rest of chunks inside this one.
- ChunkReader(f, ind, p);
- }
-
- void SpotLightReader(FILE *f, int ind, long p) {
- float c[5];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s Target X: %f, Y: %f, Z: %f; Hotspot %f, Falloff %f\n",
- ind, "", c[0], c[1], c[2], c[3], c[4]);
- }
-
- void CameraReader(FILE *f, int ind, long p) {
- float c[8];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s Position: X: %f, Y: %f, Z: %f\n", ind, "", c[0], c[1], c[2]);
- printf("%*s Target: X: %f, Y: %f, Z: %f\n", ind, "", c[3], c[4], c[5]);
- printf("%*s Bank: %f, Lens: %f\n", ind, "", c[6], c[7]);
- }
-
- void MatNameReader (FILE *f, int ind, long p) {
- int c;
-
- // Read ASCIIZ object name
- printf("%*sMaterial name \"", ind, "");
- while ( (c = fgetc(f)) != EOF && c != '\0')
- putchar(c);
- printf("\"\n");
- }
-
- void MapFileReader (FILE *f, int ind, long p) {
- int c;
-
- // Read ASCIIZ filename
- printf("%*sMap filename \"", ind, "");
- while ( (c = fgetc(f)) != EOF && c != '\0')
- putchar(c);
- printf("\"\n");
- }
-
- void FramesReader(FILE *f, int ind, long p) {
- dword c[2];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- printf("%*s Start: %ld, End: %ld\n",
- ind, "", c[0], c[1]);
- }
-
- // ------------------------------------
-
- struct {
- word id;
- const char *name;
- void (*func)(FILE *f, int ind, long p);
- } ChunkNames[] = {
- {CHUNK_RGBF, "RGB float", RGBFReader},
- {CHUNK_RGBB, "RGB byte", RGBBReader},
-
- {CHUNK_MAIN, "Main", NULL},
- {CHUNK_OBJMESH, "Object Mesh", NULL},
- {CHUNK_BKGCOLOR, "Background color", NULL},
- {CHUNK_AMBCOLOR, "Ambient color", NULL},
- {CHUNK_OBJBLOCK, "Object Block", ObjBlockReader},
- {CHUNK_TRIMESH, "Tri-Mesh", NULL},
- {CHUNK_VERTLIST, "Vertex list", VertListReader},
- {CHUNK_FACELIST, "Face list", FaceListReader},
- {CHUNK_FACEMAT, "Face material", FaceMatReader},
- {CHUNK_MAPLIST, "Mappings list", MapListReader},
- {CHUNK_SMOOLIST, "Smoothings", SmooListReader},
- {CHUNK_TRMATRIX, "Matrix", TrMatrixReader},
- {CHUNK_LIGHT, "Light", LightReader},
- {CHUNK_SPOTLIGHT, "Spotlight", SpotLightReader},
- {CHUNK_CAMERA, "Camera", CameraReader},
-
- {CHUNK_MATERIAL, "Material", NULL},
- {CHUNK_MATNAME, "Material name", MatNameReader},
- {CHUNK_AMBIENT, "Ambient color", NULL},
- {CHUNK_DIFFUSE, "Diffuse color", NULL},
- {CHUNK_SPECULAR, "Specular color", NULL},
- {CHUNK_TEXTURE, "Texture map", NULL},
- {CHUNK_BUMPMAP, "Bump map", NULL},
- {CHUNK_MAPFILE, "Map filename", MapFileReader},
-
- {CHUNK_KEYFRAMER, "Keyframer data", NULL},
- {CHUNK_FRAMES, "Frames", FramesReader},
-
- };
-
- int FindChunk(word id) {
- int i;
- for (i = 0; i < sizeof(ChunkNames)/sizeof(ChunkNames[0]); i++)
- if (id == ChunkNames[i].id)
- return i;
- return -1;
- }
-
- // ------------------------------------
-
- int Verbose = 0;
-
- void ChunkReader(FILE *f, int ind, long p) {
- TChunkHeader h;
- int n;
- long pc;
-
- while (ftell(f) < p) {
- pc = ftell(f);
- if (fread(&h, sizeof(h), 1, f) != 1) return;
- n = FindChunk(h.id);
- if (n < 0) {
- if (Verbose)
- printf("%*sUnknown chunk: 0x%04X, offset 0x%lX, size: %d bytes.\n",
- ind, "", h.id, pc, h.len);
- fseek(f, pc + h.len, SEEK_SET);
- } else {
- printf("%*sChunk type \"%s\", offset 0x%lX, size %d bytes\n",
- ind, "", ChunkNames[n].name, pc, h.len);
- pc = pc + h.len;
- if (ChunkNames[n].func != NULL)
- ChunkNames[n].func(f, ind + 2, pc);
- else
- ChunkReader(f, ind + 2, pc);
- fseek(f, pc, SEEK_SET);
- }
- if (ferror(f))
- break;
- }
- }
-
- // ------------------------------------
-
- extern void FinishProgram(void) {
- }
-
- void main(int argc, char *argv[]) {
- FILE *f;
- long p;
-
- if (argc < 2) {
- printf("Usage: 3DSRDR file.3ds [-verbose]\n");
- exit(1);
- }
-
- f = fopen(argv[1], "rb");
- if (f == NULL) {
- printf("Can't open %s!\n", argv[1]);
- exit(1);
- }
-
- if (argc > 2 && strcmp(argv[2], "-verbose") == 0)
- Verbose = 1;
-
- // Find file size.
- fseek(f, 0, SEEK_END);
- p = ftell(f);
- fseek(f, 0, SEEK_SET);
- // Go!
- ChunkReader(f, 0, p);
-
- FinishProgram();
- }
-